# -*- coding: utf-8 -*-
"""
简洁的Word文档转Markdown工具
功能：将docx和doc文件转换为markdown格式
"""

import os
import subprocess
from typing import Tuple, List, Optional
from pathlib import Path
from docx import Document
from docx.oxml.table import CT_Tbl
from docx.oxml.text.paragraph import CT_P
from docx.table import Table
from docx.text.paragraph import Paragraph


class DocxConverter:
    """DOCX转Markdown转换器"""
    
    def __init__(self, output_dir: Optional[Path] = None):
        """
        初始化转换器
        
        Args:
            output_dir: 输出目录，默认为output_mds
        """
        if output_dir is None:
            self.output_dir = Path(__file__).parent / "output_mds"
        else:
            self.output_dir = Path(output_dir)
        
        self.output_dir.mkdir(parents=True, exist_ok=True)
    
    def convert(self, input_file: str, output_file: Optional[str] = None) -> Tuple[str, List[str]]:
        """
        转换docx或doc文件为markdown
        
        Args:
            input_file: 输入的docx或doc文件路径
            output_file: 输出的md文件路径，如果为None则自动生成
            
        Returns:
            Tuple[str, List[str]]: (markdown文件路径, 图片文件路径列表)
        """
        input_path = Path(input_file)
        
        # 如果是.doc格式，先转换为.docx
        if input_path.suffix.lower() == '.doc':
            print("检测到.doc格式，正在转换为.docx...")
            input_file = self._convert_doc_to_docx(input_file)
        
        doc = Document(input_file)
        markdown_content = []
        
        # 提取图片
        image_count = 1
        image_paths = []
        for rel in doc.part.rels.values():
            if 'image' in rel.target_ref:
                image_data = rel.target_part.blob
                image_name = f'image_{image_count}.png'
                image_path = self.output_dir / image_name
                with open(image_path, 'wb') as f:
                    f.write(image_data)
                image_paths.append(str(image_path))
                image_count += 1
        
        # 标题
        title = doc.core_properties.title or Path(input_file).stem
        if output_file is None:
            output_file = str(self.output_dir / f"{title}.md")
        
        markdown_content.append(f"# {title}\n")
        
        # 正文
        for element in doc.element.body:
            if isinstance(element, CT_P):
                paragraph = Paragraph(element, doc)
                text = self._process_paragraph(paragraph)
                if text:
                    markdown_content.append(text)
            elif isinstance(element, CT_Tbl):
                table = Table(element, doc)
                table_md = self._process_table(table)
                if table_md:
                    markdown_content.append(table_md)
        
        # 添加图片
        for idx, image_path in enumerate(image_paths, 1):
            markdown_content.append(f'![图片{idx}](image_{idx}.png)\n')
        
        md_content = '\n'.join(markdown_content)
        
        # 保存文件
        output_path = Path(output_file)
        output_path.parent.mkdir(parents=True, exist_ok=True)
        
        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(md_content)
        
        return str(output_path), image_paths
    
    def _convert_doc_to_docx(self, doc_file: str) -> str:
        """
        将.doc文件转换为.docx文件
        
        Args:
            doc_file: .doc文件路径
            
        Returns:
            str: 转换后的.docx文件路径
        """
        doc_path = Path(doc_file)
        docx_path = self.output_dir / f"{doc_path.stem}_temp.docx"
        
        # 方法1: 尝试使用libreoffice/soffice命令行工具
        try:
            # 检查是否安装了LibreOffice
            soffice_paths = [
                '/Applications/LibreOffice.app/Contents/MacOS/soffice',  # macOS
                'soffice',  # Linux
                'C:\\Program Files\\LibreOffice\\program\\soffice.exe',  # Windows
            ]
            
            soffice_cmd = None
            for path in soffice_paths:
                if os.path.exists(path) or path == 'soffice':
                    soffice_cmd = path
                    break
            
            if soffice_cmd:
                # 使用LibreOffice转换
                subprocess.run([
                    soffice_cmd,
                    '--headless',
                    '--convert-to', 'docx',
                    '--outdir', str(self.output_dir),
                    str(doc_path.absolute())
                ], check=True, capture_output=True)
                
                # 重命名转换后的文件
                converted_file = self.output_dir / f"{doc_path.stem}.docx"
                if converted_file.exists():
                    converted_file.rename(docx_path)
                    print(f"✓ 已使用LibreOffice转换.doc为.docx")
                    return str(docx_path)
        except Exception as e:
            print(f"LibreOffice转换失败: {e}")
        
        # 方法2: 尝试使用pypandoc
        try:
            import pypandoc
            pypandoc.convert_file(
                str(doc_path.absolute()),
                'docx',
                outputfile=str(docx_path)
            )
            print(f"✓ 已使用pypandoc转换.doc为.docx")
            return str(docx_path)
        except Exception as e:
            print(f"pypandoc转换失败: {e}")
        
        # 方法3: 尝试使用win32com (仅Windows)
        try:
            import win32com.client
            word = win32com.client.Dispatch("Word.Application")
            word.Visible = False
            doc = word.Documents.Open(str(doc_path.absolute()))
            doc.SaveAs(str(docx_path.absolute()), FileFormat=16)  # 16 = docx格式
            doc.Close()
            word.Quit()
            print(f"✓ 已使用Microsoft Word转换.doc为.docx")
            return str(docx_path)
        except Exception as e:
            print(f"Microsoft Word转换失败: {e}")
        
        raise Exception(
            "无法转换.doc文件。请安装以下工具之一：\n"
            "1. LibreOffice: https://www.libreoffice.org/\n"
            "2. pypandoc: pip install pypandoc\n"
            "3. Microsoft Word (Windows)\n"
            "或者手动将.doc文件另存为.docx格式"
        )
    
    def _process_paragraph(self, paragraph: Paragraph) -> str:
        """处理段落"""
        text = paragraph.text.strip()
        if not text:
            return ""
        
        try:
            style = paragraph.style.name.lower() if paragraph.style and paragraph.style.name else ""
        except:
            style = ""
        
        if 'heading' in style:
            level = style.replace('heading', '').replace(' ', '')
            if level.isdigit():
                return f"{'#' * int(level)} {text}\n"
            else:
                return f"## {text}\n"
        elif 'list' in style:
            return f"- {text}\n"
        else:
            run_texts = []
            for run in paragraph.runs:
                run_text = run.text
                if run.bold:
                    run_text = f"**{run_text}**"
                if run.italic:
                    run_text = f"*{run_text}*"
                if run.underline:
                    run_text = f"<u>{run_text}</u>"
                run_texts.append(run_text)
            return ''.join(run_texts) + '\n'
    
    def _process_table(self, table: Table) -> str:
        """处理表格"""
        if not table.rows:
            return ""
        
        markdown_table = []
        
        for i, row in enumerate(table.rows):
            row_cells = []
            for cell in row.cells:
                cell_text = ""
                for paragraph in cell.paragraphs:
                    cell_text += self._process_paragraph(paragraph).strip()
                row_cells.append(cell_text)
            
            markdown_table.append("| " + " | ".join(row_cells) + " |")
            
            if i == 0:
                markdown_table.append("| " + " | ".join(["---"] * len(row_cells)) + " |")
        
        return '\n'.join(markdown_table) + '\n'
